home *** CD-ROM | disk | FTP | other *** search
-
- package LWP::Protocol::http;
-
- require LWP::Debug;
- require LWP::Protocol;
- require LWP::Socket;
- require HTTP::Request;
- require HTTP::Response;
- require HTTP::Status;
-
- use Carp ();
-
- @ISA = qw(LWP::Protocol);
-
- use strict;
-
- my $httpversion = 'HTTP/1.0'; # for requests
- my $endl = "\015\012"; # how lines should be terminated;
-
- sub _new_socket
- {
- LWP::Socket->new;
- }
-
- sub request
- {
- my($self, $request, $proxy, $arg, $size, $timeout) = @_;
- LWP::Debug::trace('()');
-
- $size ||= 4096;
-
- my $method = $request->method;
- unless ($method =~ /^[A-Za-z0-9_!#\$%&'*+\-.^`|~]+$/) { # HTTP token
- return new HTTP::Response &HTTP::Status::RC_BAD_REQUEST,
- 'Library does not allow method ' .
- "$method for 'http:' URLs";
- }
-
- my $url = $request->url;
- my($host, $port, $fullpath);
-
- if (defined $proxy) {
- $host = $proxy->host;
- $port = $proxy->port;
- $fullpath = $url->as_string;
- }
- else {
- $host = $url->host;
- $port = $url->port;
- $fullpath = $url->full_path;
- }
-
- alarm($timeout) if $self->use_alarm and $timeout;
-
- my $socket = $self->_new_socket();
- $socket->connect($host, $port);
-
- my $request_line = "$method $fullpath $httpversion$endl";
-
-
- my $content = $request->content;
-
- my $contRef;
- if (defined $content){
- $contRef = ref($content) ? $content : \$content;
- if (ref($contRef) eq 'SCALAR') {
- $request->header('Content-Length', length $$contRef)
- if length $$contRef;
- } elsif (ref($contRef) eq 'CODE') {
- Carp::croak('No Content-Length header for request with content')
- unless $request->header('Content-Length');
- } else {
- Carp::croak("Illegal content in request ($content)");
- }
- }
-
- $request->header('Host', $url->netloc);
-
- $socket->write($request_line . $request->headers_as_string($endl) . $endl);
- if (defined $content) {
- if (ref($contRef) eq 'CODE') {
- $socket->write($contRef, $timeout);
- } else {
- $socket->write($$contRef, $timeout);
- }
- }
-
- LWP::Debug::debug('reading response');
-
- my $res = "";
- my $buf = "";
- my $response;
-
- while ($socket->read(\$buf, undef, $timeout)) {
- $res .= $buf;
- if ($res =~ s/^(HTTP\/\d+\.\d+)[ \t]+(\d+)[ \t]*([^\012]*)\012//) {
- my($ver,$code,$msg) = ($1, $2, $3);
- $msg =~ s/\015$//;
- LWP::Debug::debug("$ver $code $msg");
- $response = HTTP::Response->new($code, $msg);
- $response->protocol($ver);
-
- while ($res !~ /\015?\012\015?\012/) {
- LWP::Debug::debug("need more data for headers");
- last unless $socket->read(\$buf, undef, $timeout);
- $res .= $buf;
- }
-
- my($key, $val);
- while ($res =~ s/([^\012]*)\012//) {
- my $line = $1;
-
- my $save = "$line\012";
-
- $line =~ s/\015$//;
- last unless length $line;
-
- if ($line =~ /^([a-zA-Z0-9_\-]+)\s*:\s*(.*)/) {
- $response->push_header($key, $val) if $key;
- ($key, $val) = ($1, $2);
- } elsif ($line =~ /^\s+(.*)/) {
- unless ($key) {
- LWP::Debug::debug("Illegal continuation header");
- $res = "$save$res";
- last;
- }
- $val .= " $1";
- } else {
- LWP::Debug::debug("Illegal header '$line'");
- $res = "$save$res";
- last;
- }
- }
- $response->push_header($key, $val) if $key;
- last;
-
- } elsif ((length($res) >= 5 and $res !~ /^HTTP\//) or
- $res =~ /\012/ ) {
- LWP::Debug::debug("HTTP/0.9 assume OK");
- $response = HTTP::Response->new(&HTTP::Status::RC_OK, "OK");
- $response->protocol('HTTP/0.9');
- last;
-
- } else {
- LWP::Debug::debug("need more data to know which protocol");
- }
- };
- die "Unexpected EOF" unless $response;
-
- $socket->pushback($res) if length $res;
- $response->request($request);
-
- alarm($timeout) if $self->use_alarm and $timeout;
-
- $response = $self->collect($arg, $response, sub {
- LWP::Debug::debug('Collecting');
- my $content = '';
- my $result = $socket->read(\$content, $size, $timeout);
- return \$content;
- } );
- $socket = undef; # close it
-
- $response;
- }
-
- 1;
-